[小ネタ] CLIからCloudFormation StackSetsを作成する方法
小ネタです。
ちょっとお仕事でGuardDutyを各リージョンに導入する必要があり、以下の記事を参考にCloudFormationのStackSetsを作成しようとしました。
作業自体はシンプルなものであるためマネジメントコンソールからポチポチ実行しても良いだろうと思ったのですが、いざマネジメントコンソールからStackSetsを作り各リージョンに対してスタックインスタンスを増やそうと「すべてのリージョン」ボタンをクリックしてやると、
こんな感じでアフリカ(ケープタウン)
やアジアパシフィック(香港)
などデフォルト無効でオプトアウトしているリージョンまで候補に含まれてしまいます。
(「すべてのリージョン」で追加されるリージョンはオプトインの状況を判断してくれない...どうして...)
これだけであればオプトインしていないリージョンを手作業で「削除」すれば構いませんが、今回は複数アカウント同様の作業をする必要があったためめんどうくさいという気持ちになり、マネジメントコンソールの使用を止めCLIからStackSetsを作ることにしました。
CLIでStackSetsを作る基本
マネジメントコンソールからウィザードでStackSetsを作る場合、StackSetsの定義と対象リージョンの指定を一度に行いますが、APIとしてはそれぞれ別であり、CLIから行う場合も二段階に分けて以下のコマンドを実行してやる必要があります。
- CreateStackSet API : StackSetsの定義を作成
- AWS Tools for PowerShell : New-CFNStackSet
- AWS CLI : aws cloudformation create-stack-set
- CreateStackInstances API : StackSetsに対しアカウント、リージョン毎のスタックインスタンスを作成
- AWS Tools for PowerShell : New-CFNStackInstance
- AWS CLI : aws cloudformation create-stack-instances
AWS Tools for PowerShellを使ってStackSetsを作る
私はメインでAWS Tools for PowerShellを使うので最初にAWS Tools for PowerShellでの手順を紹介します。
検証環境
動作確認は以下の環境で行っています。
- 64bit版 Windows 10 Pro (Ver.20H2)
- PowerShell 7.1.0
- AWS Tools for PowerShell 4.1.5
- AWS.Tools.CloudFormation, AWS.Tools.EC2 モジュールを使用
0. 前準備
前準備としてStackSetsを利用するために必要なAWSCloudFormationStackSetAdministrationRole
ロールおよびAWSCloudFormationStackSetExecutionRole
ロールは以下のコマンドで作成できます。
公開されているテンプレートをNew-CFNStackを使って作成しているだけです。
注意点としてはIAMロールを作るためCapabilityパラメーターにCAPABILITY_IAM
とCAPABILITY_NAMED_IAM
を指定する必要があるくらいです。
# AWSCloudFormationStackSetAdministrationRole ロールの作成
$params = @{
StackName = 'CFnStackSets-AdministrationRole-Stack'
TemplateURL ='https://s3.amazonaws.com/cloudformation-stackset-templates-us-east-1/master_account_role.template'
Capability = @('CAPABILITY_IAM', 'CAPABILITY_NAMED_IAM')
}
New-CFNStack @params
以下の例ではGet-STSCallerIdentityを使ってMasterアカウントを自分自身のアカウントにしています。
他のアカウントにする場合は決め打ちで指定してください。
# AWSCloudFormationStackSetExecutionRole ロールの作成
$params = @{
StackName = 'CFnStackSets-ExecutionRole-Stack'
TemplateURL ='https://s3.amazonaws.com/cloudformation-stackset-templates-us-east-1/managed_account_role.template'
Parameter = @(
@{ParameterKey = 'MasterAccountId'; ParameterValue = (Get-STSCallerIdentity -Select Account)} # 自分自身のアカウントを管理
)
Capability = @('CAPABILITY_IAM', 'CAPABILITY_NAMED_IAM')
}
New-CFNStack @params
1. New-CFNStack の実行
New-CFNStackSetの使い方はこんな感じです。
New-CFNStackと似てますのでそんなに困ることは無いかと思います。
$params = @{
StackSetName = 'GuardDuty-for-All-Regions'
Description = 'Enable GuardDuty and set SNS alert'
Parameter = @(
@{ParameterKey = 'MailAddress'; ParameterValue = 'your-email@example.com'}
)
TemplateURL = 'https://s3-ap-northeast-1.amazonaws.com/pub-codes-9nvushbw/templates/guardduty-sns.template'
}
New-CFNStackSet @params
これでスタックインスタンスが無い状態のStackSetsを作成できます。
2. New-CFNStackInstance の実行
次にこのStackSetsに対してNew-CFNStackInstanceを使い各リージョン毎のスタックインスタンスを増やしてやります。
先に手順を示しておくと、以下の様にすると自身のアカウントのオプトインされた全リージョンに対してスタックインスタンスを作成します。
$params = @{
StackSetName = 'GuardDuty-for-All-Regions'
Account = (Get-STSCallerIdentity -Select Account) # 今回は自身のアカウントのみ
StackInstanceRegion = (Get-EC2Region -Select Regions.RegionName) # オプトインされたリージョンのみを取得
OperationPreference = [Amazon.CloudFormation.Model.StackSetOperationPreferences]@{
MaxConcurrentCount = 1
FailureToleranceCount = 0
}
}
New-CFNStackInstance @params
これでオプトインしているリージョンだけに対してインスタンスを作りますので後は完了を待つだけになります。
オプトインされたリージョンのみを取得する方法
New-CFNStackInstance
では-StackInstanceRegion
パラメーターにインスタンスを作るリージョン名の配列を渡してやります。
オプトインの状態を含めたリージョン情報はGet-EC2Regionで取得可能であり、引数なしで実行した場合オプトインしているリージョンのみ取得できます。
オプトアウトしているリージョンも合わせて欲しい場合は-AllRegion
パラメーターを指定してやります。
このため、
Get-EC2Region -Select Regions.RegionName
とすることでオプトインしているリージョン名の一覧を取得できます。
AWS CLIを使ってStackSetsを作る
続けてAWS CLIを使った手順を紹介します。
検証環境
動作確認は以下の環境で行っています。
- Ubuntu 18.04 on WSL2
- AWS CLI 2.1.7 + Bash 4.4.20
0. 前準備
AWSCloudFormationStackSetAdministrationRole
ロールおよびAWSCloudFormationStackSetExecutionRole
ロールは以下のコマンドで作成できます。
# AWSCloudFormationStackSetAdministrationRole ロールの作成
aws cloudformation create-stack \
--stack-name CFnStackSets-AdministrationRole-Stack \
--template-url https://s3.amazonaws.com/cloudformation-stackset-templates-us-east-1/master_account_role.template \
--capabilities CAPABILITY_IAM CAPABILITY_NAMED_IAM
# AWSCloudFormationStackSetExecutionRole ロールの作成
aws cloudformation create-stack \
--stack-name CFnStackSets-ExecutionRole-Stack \
--template-url https://s3.amazonaws.com/cloudformation-stackset-templates-us-east-1/managed_account_role.template \
--parameters ParameterKey=MasterAccountId,ParameterValue=$(aws sts get-caller-identity --query Account --output text) \
--capabilities CAPABILITY_IAM CAPABILITY_NAMED_IAM
1. aws cloudformation create-stack-set の実行
aws cloudformation create-stack-setの使い方はこんな感じです。
aws cloudformation create-stack-set \
--stack-set-name GuardDuty-for-All-Regions \
--description 'Enable GuardDuty and set SNS alert' \
--parameters ParameterKey=MailAddress,ParameterValue=your-email@example.com \
--template-url https://s3-ap-northeast-1.amazonaws.com/pub-codes-9nvushbw/templates/guardduty-sns.template
2. aws cloudformation create-stack-instances の実行
aws cloudformation create-stack-instancesの使い方はこんな感じです。
aws cloudformation create-stack-instances \
--stack-set-name GuardDuty-for-All-Regions \
--accounts $(aws sts get-caller-identity --query Account --output text) \
--regions $(aws ec2 describe-regions --query Regions[*].RegionName --output text | tr '\t' ' ') \
--operation-preferences MaxConcurrentCount=1,FailureToleranceCount=0
やっていることはPowerShellの場合と同様です。
aws ec2 describe-regionsでオプトインしているリージョンの一覧を取得しています。
最後に
ざっとこんな感じです。
知ってしまえば大した内容ではありませんがそれなりに役に立つことがあるかと思います。